matlab/simulink中带参数的S 您所在的位置:网站首页 function create matlab/simulink中带参数的S

matlab/simulink中带参数的S

2023-11-17 15:24| 来源: 网络整理| 查看: 265

S函数的相关概念与写法,直接在帮助文件中搜:【MATLAB S-Functions Create custom blocks defined】、【S-Function Concepts】等

 

S函数模块可以从下图中拖出来:

图 1

其中S-Function是正宗的S函数模块,旁边还有一个S-Function builder是给新手用的,只要学会了S函数模块,S builder模块自然一看就懂。

使用S函数模块的步骤:①写S函数的.m文件, 并把m文件所在的文件夹加入搜索路径,如下图2所示。②在simulink中拖出S函数,并填上m文件的名字,如果有参数(下文会讲到),也把参数名填上,如下图3所示。然后就可以执行仿真了

图2

图3

 

下面是最关键的部分,如何写S函数:

写S函数的本质就是写一堆回调函数,C/C++程序员对回调函数应该很熟悉了,既然是回调函数,那写之前必须要知道形参和返回值的格式,这个格式从哪查?直接在matlab命令行执行: edit sfuntmpl,就直接打开了官方提供的模板,连格式都不用查了,直接仿照官方模板把函数体改改盖就行了,方便。

(1)S函数的总函数

把官方模板的代码拷到一个新文件里,并命名为自定义名称,我取的名字是oneOrderModule.m,然后把函数名也改成和文件名相同,我的是这样的:function [sys,x0,str,ts,simStateCompliance] = oneOrderModule(t,x,u,flag, T)

我与官方版不同的是,自己加了一个参数T,如果你还想添加更多参数,直接在形参表里添加就行了。添加的形参的实参值,来自于图3的第二个输入框,这个输入框可填常量,也可以填工作区变量名。

形参:①当前的仿真时间t,单位为秒,该参数可以用来描述变参数系统,例如你想实现【在t>2S时,把系统增益给改掉】这一功能,就可以通过判定t的值来实现;②x为状态列向量;③输入列向量u;④flag为当前状态机的第几步,例如实参送进来的flag=0代表S函数需要初始化,flag=1代表要更新连续状态

返回值:在不同的状态步下(也即flag不同时),返回值的意义是不同的,在模板文件的注释中都讲到了:

例如flag=0时,需要返回:输入输出状态变量等的大小SIZES、状态变量的初值X0等。。。 又如flag=3时,返回值sys代表输出向量Y,也即状态空间表达式第2式,Y=CX+DU

不同flag下返回值得写法,将在下面的各个函数中依次讲解

(2)系统初始化

当我么在函数中检测到flag=0时,意味着simulnk需要我们返回系统初始化的一些信息。 实际上,我们可以直接把flag=0时需要执行的代码直接写在switch-case中,但是为了使程序更清晰,我们也仿照官方模板,在case中调用初始化函数mdlInitializeSizes,我们把代码写在初始化函数中。

function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes sizes = simsizes; sizes.NumContStates = 1;%连续状态向量的元素数目 sizes.NumDiscStates = 0;%离散状态向量的元素数目 sizes.NumOutputs = 2;%输出向量的元素数目 sizes.NumInputs = 1;%输入向量的元素数目 sizes.DirFeedthrough = 1;%输入是否直接馈通到输出 sizes.NumSampleTimes = 1; % 采样时间矩阵的行数(必须设为>=1),另外列数固定为2,无需设置 sys = simsizes(sizes);%把以上赋值好的结构赋给返回值 x0 = [0];%设置状态向量的初值 str = [];%保留参数,不用管 ts = [0 0];%采样时间设置,必须为mx2维度,其中m为上面sizes.NumSampleTimes的值 simStateCompliance = 'UnknownSimState';

此函数中,按照回调函数的要求,sys的返回要返回一些成员的尺寸大小,我们可以一个个为sys(1)、sys(2)。。等依次赋值,但我们不会这么做,因为官方模板为我们提供了一个辅助数据结构的实体simsizes,直接把他复制出来把成员值改好,再赋值给返回值sys即可。simsizes的成员有6个,其中有2个需要单独讲一下:

①直接馈通标志DirFeedthrough,这个东西实际上就是看看状态空间表达式第2式Y=CX+DU中的D矩阵是否为0矩阵,如果不是,那我们必须把馈通标志设为1。从回调函数来看,只要我们把DirFeedthrough设成了1,那么当flag=3时,系统会把t、u两个参数传进总函数oneOrderModule中,如果DirFeedthrough设成了0,那么当flag=3时,我们在oneOrderModule函数或者mdlOutputs函数中中将无法读到t的值(实际读出来总是0),也无法读到u的值(实际读出来总是一个只含Nan元素的向量)。

②采样时间矩阵的行数NumSampleTimes 这个东西有些复杂,从直观上看,它决定了【采样时间矩阵ts】的行数,ts矩阵是NumSampleTimes行2列的矩阵。ts的每一行均包含一个数据对:[ 采样时间   偏移量 ],这些数据对不是乱填的,可选就这么几种形式:

采样时间可以理解为采样周期,真正的采样时刻=n*周期+偏移量。 对于连续系统,采样时间应设为0,matlab也提供宏CONTINUOUS_SAMPLE_TIME,该宏的值=0。 对于固定步长的离散系统,可以直接设置采样间隔和偏移,形如:[ 0.1   0.02 ] 对于变步长的离散系统,可以设置为:[VARIABLE_SAMPLE_TIME,  0.0],这种参数需要同时把simulink求解器solver设置成变步长的。 继承前一模块的采样点,可以设置为:[INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET或0]。

更多知识点,可以搜索这几个宏名来学习。

 

(3)连续系统更新、离散系统更新

这两个函数分别为mdlDerivatives和mdlUpdate,如果需要支持自定义的参数,那么直接修改函数的形参表即可,在我的例子中,我附加了一个T参数,那么我的连续系统更新函数是这样的:

function sys=mdlDerivatives(t,x,u, T) A = [-1/T]; B = [1/T]; sys = A*x+B*u;

原理是这样的,典型一阶系统的微分方程:

如果系统中存在离散状态,那么就在mdlUpdate中写出离散状态空间表达式即可,如果没有离散状态,就直接sys返回空矩阵。

(4)输出函数

function sys=mdlOutputs(t,x,u) C = [1 1]; D = [0 1]; sys = C * x + D * u; %sys = [x t];

这个也没啥好说的,描述一下输出向量即可。不过提醒一下,如果使用了 u或t 参数,不要忘记把馈通标志置1,否则在本函数中收不到t和u的实参值。

这个函数描述了两个输出: y(1)=x,y(2)=x+u

 

 

下面看一下仿真结果:

和预想的一样,没毛病。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有